﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using MvcEngine.Core.Repositories;

using System.Web;
using MvcEngine.Core;
using MvcEngine.Mvc.Models.ViewModels;
using MvcEngine.Core.Content;
using MvcEngine.Core.Helpers;

namespace MvcEngine.Mvc.Filters
{
    public class PageActionFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            int? ctrId = null;
            Control control = null;
            Page page = null;

            if (filterContext.RouteData.Values.ContainsKey("controlKey"))
            {
                control = ContentManager.Current.GetControlByKey(filterContext.RouteData.Values["controlKey"].ToString());
            }

            if (filterContext.RouteData.Values.ContainsKey("pageName"))
            {
                string pageName = filterContext.RouteData.Values["pageName"].ToString();
                if (!string.IsNullOrEmpty(pageName) && pageName != "default.aspx")
                {
                    page = ContentManager.Current.GetPage(pageName);
                    if (page == null)
                    {
                        LogHelper.Current.WriteError(string.Format("Page '{0}' Not Found.", pageName));
                        throw new PageNotFoundException(string.Format("Page '{0}' is not found", pageName));
                    }
                }
            }

            if (page == null)
                page = SiteContext.Current.CurrentPage;

            if (!page.Visible)
            {
#warning log error
                throw new PageNotFoundException(string.Format("Page '{0}' is not found", page.Name));
            }

            if (!PermissionHelper.Current.HasRights(page.Id, PermissionTypes.View))
            {
                throw new PermissionException(string.Format("Access forbiden ot page '{0}' ", page.Name));
            }

            if (control != null && page != null)
            {
                Module module = ContentManager.Current.GetModule(control.ModuleId);
                filterContext.RouteData.Values["moduleName"] = module.Name;

                //TODO: think about what if control was added to a page in any way
                PageContent pc = IoC.Resolve<IPageContentRepository>().Get(page.Id, control.Id).SingleOrDefault();
                if (pc != null)
                {
                    AddValuesToContext(filterContext, "ctrId", pc.Id);
                    if (pc.ReferenceId.HasValue)
                        AddValuesToContext(filterContext, "ctrReferenceId", pc.ReferenceId.Value);
                    ctrId = pc.Id;
                }
                else
                {
                    //Throw an exception because control is not present on a page.
                }
            }

            if (!ctrId.HasValue && filterContext.RouteData.Values.ContainsKey("ctrId"))
            {
                int result;
                if (int.TryParse(filterContext.RouteData.Values["ctrId"].ToString(), out result))
                {
                    ctrId = result;
                }
            }

            if (control != null)
            {
                Module module = ContentManager.Current.GetModule(control.ModuleId);
                filterContext.RouteData.Values["moduleName"] = module.Name;

                AddValuesToContext(filterContext, "controlId", control.Id);
                //AddValuesToContext(filterContext, "controllerType", control.ControllerType);
            }
            else
            {
                if (ctrId.HasValue)
                {
                    PageContent pageContent = ContentManager.Current.GetPageContent(ctrId.Value);
                    control = ContentManager.Current.GetControl(pageContent.ControlId);
                    AddValuesToContext(filterContext, "controlId", control.Id);
                }
            }

            AddValuesToContext(filterContext, "pageName", page.Name);
            AddValuesToContext(filterContext, "pageId", page.Id);

        }

        private void AddValuesToContext(ActionExecutingContext filterContext, string key, object value)
        {
            filterContext.ActionParameters[key] = value;
            filterContext.RouteData.Values[key] = value;
        }
    }
}
